package cl.sodexo.com.dao;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.apache.log4j.Logger;

import cl.sodexo.com.dto.Estado;
import cl.sodexo.com.dto.Requerimiento;
import cl.sodexo.com.dto.TipoRequerimiento;
import cl.sodexo.com.dto.Usuario;
import cl.sodexo.com.utils.FechaUtils;

public class RequerimientoDAO extends AbstractDAO{
	
	private static final Logger logger 	= Logger.getLogger(RequerimientoDAO.class);
	private static final String ASC		= " ASC ";
	private static final String DESC	= " DESC ";
	private static final String orderBy = " ORDER BY ";
	private static final String ID		= " r.idRequerimiento ";
	private static final String ESTADO	= " r.estado ";
	private static final String JEFEPRO = " r.jefeProyecto ";
	private static final String F_INGRE = " r.fechaIngreso ";
	
	/**
	 * @param idUsuario
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientos(String idUsuario) throws SQLException{
		return this.getRequerimientosOrderByIdASC(idUsuario);
	}
	
	/**
	 * @param idUsuario
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosOrderByIdASC(String idUsuario) throws SQLException{
		return this.getRequerimientosOrderBy(idUsuario, orderBy + ID + ASC);
	}
	
	/**
	 * @param idUsuario
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosOrderByIdDESC(String idUsuario) throws SQLException{
		return this.getRequerimientosOrderBy(idUsuario, orderBy + ID + DESC);
	}
	
	/**
	 * @param idUsuario
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosOrderByEstadoASC(String idUsuario) throws SQLException{
		return this.getRequerimientosOrderBy(idUsuario, orderBy + ESTADO + ASC);
	}
	
	/**
	 * @param idUsuario
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosOrderByEstadoDESC(String idUsuario) throws SQLException{
		return this.getRequerimientosOrderBy(idUsuario, orderBy + ESTADO + DESC);
	}
	
	/**
	 * @param idUsuario
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosOrderByJefeASC(String idUsuario) throws SQLException{
		return this.getRequerimientosOrderBy(idUsuario, orderBy + JEFEPRO + ASC);
	}
	
	/**
	 * @param idUsuario
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosOrderByJefeDESC(String idUsuario) throws SQLException{
		return this.getRequerimientosOrderBy(idUsuario, orderBy + JEFEPRO + DESC);
	}
	
	/**
	 * @param idUsuario
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosOrderByFechaIngresoASC(String idUsuario) throws SQLException{
		return this.getRequerimientosOrderBy(idUsuario, orderBy + F_INGRE + ASC);
	}
	
	/**
	 * @param idUsuario
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosOrderByFechaIngresoDESC(String idUsuario) throws SQLException{
		return this.getRequerimientosOrderBy(idUsuario, orderBy + F_INGRE + DESC);
	}
	
	/**
	 * @return
	 * @throws SQLException
	 */
	private ArrayList<Requerimiento> getRequerimientosOrderBy(String idUsuario, String orderBySQL) throws SQLException{
		ArrayList<Requerimiento> requerimientos = new ArrayList<Requerimiento>();
		Connection con		= null;
		Requerimiento reqTO	= null;
		Usuario jefeTO		= null;
		Estado estadoTO		= null;
		ResultSet rs		= null;
		StringBuilder sql	= null;
		PreparedStatement ps= null;
		
		try{
			sql = new StringBuilder();
			sql.append("SELECT r.idRequerimiento AS idRequerimiento, r.detalle AS detalle, ");
			sql.append("date_format(r.fechaIngreso, '%d-%m-%Y %H:%i') AS fechaIngreso, r.tiempoEstimado AS tiempoEstimado, ");
			sql.append("date_format(r.fechaEntrega, '%d-%m-%Y') AS fechaEntrega, r.jefeProyecto AS idJefe, ");
			sql.append("u.nombre AS nombreJefe, r.estado AS idEstado, e.descEstado AS glosaEstado ");
			sql.append("FROM sodexo.requerimiento r LEFT JOIN sodexo.usuario u ON r.jefeProyecto = u.idUsuario ");
			sql.append("LEFT JOIN sodexo.estadoRequerimiento e ON r.estado = e.idEstado WHERE 1=1 ");
			
			if(idUsuario != null){
				sql.append(" AND r.usuarioSolicitante = ");
				sql.append(idUsuario);
			}
			
			if(orderBySQL != null) sql.append(orderBySQL);
			
			con = super.loadConnection();
			ps	= con.prepareStatement(sql.toString());
			rs	= ps.executeQuery();
			
			while(rs.next()){
				reqTO	= new Requerimiento();
				reqTO.setIdRequerimiento(rs.getString("idRequerimiento"));
				reqTO.setDetalle(rs.getString("detalle"));
				reqTO.setFechaIngreso(rs.getString("fechaIngreso"));
				reqTO.setTiempoEstimado(rs.getString("tiempoEstimado"));
				reqTO.setFechaEntrega(rs.getString("fechaEntrega"));
				jefeTO	= new Usuario();
				jefeTO.setIdUsuario(rs.getString("idJefe"));
				jefeTO.setNombre(rs.getString("nombreJefe"));
				reqTO.setJefeProyecto(jefeTO);
				estadoTO= new Estado();
				estadoTO.setIdEstado(rs.getString("idEstado"));
				estadoTO.setDescripcion(rs.getString("glosaEstado"));
				reqTO.setEstado(estadoTO);
				requerimientos.add(reqTO);
			}
			
		}catch (Exception e) {
			logger.error(e, e);
		}finally{
			super.closeAll(con, ps, rs);
		}
		
		return requerimientos;
	}
	
	/**
	 * @param req
	 * @return
	 * @throws SQLException
	 */
	public Boolean insertRequerimiento(Requerimiento req) throws SQLException{
		boolean resultado	= false;
		Connection con		= null;
		PreparedStatement ps= null;
		StringBuilder sql	= null;
		
		try{
			sql = new StringBuilder();
			sql.append("INSERT INTO sodexo.requerimiento ");
			sql.append("(detalle, fechaIngreso, usuarioSolicitante, tipoRequerimiento, keyBPM, filePath) ");
			sql.append("VALUES(?, now(), ?, ?, ? ,? ) ");
			
			con = super.loadConnection();
			ps	= con.prepareStatement(sql.toString());
			ps.setString(1, req.getDetalle());
			ps.setBigDecimal(2, new BigDecimal(req.getUsuarioSolicitante().getIdUsuario()));
			ps.setBigDecimal(3, new BigDecimal(req.getTipoRequerimiento().getIdTipo()));
			ps.setString(4, req.getKey());
			ps.setString(5, req.getFilePath());
			ps.executeUpdate();
			
			resultado = true;
			
		}catch (Exception e) {
			logger.error(e, e);
		}finally{
			super.closeAll(con, ps, null);
		}
		
		return resultado;
	}
	
	/**
	 * @param req
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosJefatura(Requerimiento req) throws SQLException{
		return this.getRequerimientosJefaturaOrderByIdASC(req);
	}
	
	/**
	 * @param req
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosJefaturaOrderByIdASC(Requerimiento req) throws SQLException{
		return this.getRequerimientosJefaturaOrderBy(req, orderBy + ID + ASC);
	}
	
	/**
	 * @param req
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosJefaturaOrderByIdDESC(Requerimiento req) throws SQLException{
		return this.getRequerimientosJefaturaOrderBy(req, orderBy + ID + DESC);
	}
	
	/**
	 * @param req
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosJefaturaOrderByEstadoASC(Requerimiento req) throws SQLException{
		return this.getRequerimientosJefaturaOrderBy(req, orderBy + ESTADO + ASC);
	}
	
	/**
	 * @param req
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosJefaturaOrderByEstadoDESC(Requerimiento req) throws SQLException{
		return this.getRequerimientosJefaturaOrderBy(req, orderBy + ESTADO + DESC);
	}
	
	/**
	 * @param req
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosJefaturaOrderByJefeASC(Requerimiento req) throws SQLException{
		return this.getRequerimientosJefaturaOrderBy(req, orderBy + JEFEPRO + ASC);
	}
	
	/**
	 * @param req
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosJefaturaOrderByJefeDESC(Requerimiento req) throws SQLException{
		return this.getRequerimientosJefaturaOrderBy(req, orderBy + JEFEPRO + DESC);
	}
	
	/**
	 * @param req
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosJefaturaOrderByFechaIngresoASC(Requerimiento req) throws SQLException{
		return this.getRequerimientosJefaturaOrderBy(req, orderBy + F_INGRE + ASC);
	}
	
	/**
	 * @param req
	 * @return
	 * @throws SQLException
	 */
	public ArrayList<Requerimiento> getRequerimientosJefaturaOrderByFechaIngresoDESC(Requerimiento req) throws SQLException{
		return this.getRequerimientosJefaturaOrderBy(req, orderBy + F_INGRE + DESC);
	}
	
	/**
	 * @return
	 * @throws SQLException
	 */
	private ArrayList<Requerimiento> getRequerimientosJefaturaOrderBy(Requerimiento req, String orderBySQL) throws SQLException{
		ArrayList<Requerimiento> requerimientos = new ArrayList<Requerimiento>();
		Connection con			= null;
		Requerimiento reqTO		= null;
		Usuario userTO			= null;
		Usuario jefeTO			= null;
		Usuario jefeGralTO		= null;
		TipoRequerimiento tipoTO= null;
		Estado estadoTO			= null;
		ResultSet rs			= null;
		StringBuilder sql		= null;
		PreparedStatement ps	= null;
		
		try{
			sql = new StringBuilder();
			sql.append("SELECT r.idRequerimiento AS idRequerimiento, r.usuarioSolicitante AS idUsuario, ");
			sql.append("r.jefeProyecto AS idJefe, ");
			sql.append("(SELECT j.nombre FROM sodexo.usuario j WHERE j.idUsuario = r.jefeProyecto) AS nombreJefeProyecto, ");
			sql.append("u.nombre AS nombreUsuario, r.detalle AS detalle, date_format(r.fechaIngreso, '%d-%m-%Y') AS fechaIngreso, ");
			sql.append("r.tipoRequerimiento AS idTipo, t.descTipo AS glosaTipo, r.tiempoEstimado as tiempoEstimado, ");
			sql.append("date_format(r.fechaEntrega, '%d-%m-%Y') AS fechaEntrega, r.respuesta AS respuesta, ");
			sql.append("r.estado AS idEstado, (SELECT e.descEstado FROM sodexo.estadoRequerimiento e WHERE e.idEstado = r.estado) AS glosaEstado, ");
			sql.append("r.keyBPM AS keyBpm, r.filePath AS filePath, r.jefaturaGral AS idJefaturaGral, ");
			sql.append("(SELECT g.nombre FROM sodexo.usuario g WHERE g.idUsuario = r.jefaturaGral) AS nombreJefeGral ");
			sql.append("FROM sodexo.requerimiento r LEFT JOIN sodexo.tipoRequerimiento t ");
			sql.append("ON r.tipoRequerimiento = t.idTipo ");
			sql.append("INNER JOIN sodexo.usuario u ON r.usuarioSolicitante = u.idUsuario ");
			sql.append("WHERE 1=1 ");
			
			if(req != null){
				if(req.getIdRequerimiento() != null){
					sql.append(" AND r.idRequerimiento = ");
					sql.append(req.getIdRequerimiento());
				}
				
				if(req.getEstado() != null){
					sql.append(" AND r.estado = ");
					sql.append(req.getEstado().getIdEstado());
				}
				
				if(req.getTipoRequerimiento() != null){
					sql.append(" AND r.tipoRequerimiento = ");
					sql.append(req.getTipoRequerimiento().getIdTipo());
				}
				
				if(req.getUsuarioSolicitante() != null){
					sql.append(" AND r.usuarioSolicitante = ");
					sql.append(req.getUsuarioSolicitante().getIdUsuario());
				}
				
				if(req.getJefaturaGral() != null){
					sql.append(" AND (r.jefaturaGral IN (");
					sql.append(req.getJefaturaGral().getIdUsuario());
					sql.append(") OR ");
					sql.append(" r.jefaturaGral IS NULL) ");
				}
			}
			
			if(orderBySQL != null) sql.append(orderBySQL);
			
			con = super.loadConnection();
			ps	= con.prepareStatement(sql.toString());			
			rs	= ps.executeQuery();
			
			while(rs.next()){
				reqTO	= new Requerimiento();
				reqTO.setIdRequerimiento(rs.getString("idRequerimiento"));
				userTO	= new Usuario();
				userTO.setIdUsuario(rs.getString("idUsuario"));
				jefeTO	= new Usuario();
				jefeTO.setIdUsuario(rs.getString("idJefe"));
				jefeTO.setNombre(rs.getString("nombreJefeProyecto"));
				reqTO.setJefeProyecto(jefeTO);
				userTO.setNombre(rs.getString("nombreUsuario"));
				reqTO.setUsuarioSolicitante(userTO);
				reqTO.setDetalle(rs.getString("detalle"));
				reqTO.setFechaIngreso(rs.getString("fechaIngreso"));
				tipoTO	= new TipoRequerimiento();
				tipoTO.setIdTipo(rs.getString("idTipo"));
				tipoTO.setDescripcion(rs.getString("glosaTipo"));
				reqTO.setTipoRequerimiento(tipoTO);
				reqTO.setTiempoEstimado(rs.getString("tiempoEstimado"));
				reqTO.setFechaEntrega(rs.getString("fechaEntrega"));
				reqTO.setRespuesta(rs.getString("respuesta"));
				estadoTO = new Estado();
				estadoTO.setIdEstado(rs.getString("idEstado"));
				estadoTO.setDescripcion(rs.getString("glosaEstado"));
				reqTO.setEstado(estadoTO);
				reqTO.setKey(rs.getString("keyBpm"));
				reqTO.setFilePath(rs.getString("filePath"));
				jefeGralTO= new Usuario();
				jefeGralTO.setIdUsuario(rs.getString("idJefaturaGral"));
				jefeGralTO.setNombre(rs.getString("nombreJefeGral"));
				reqTO.setJefaturaGral(jefeGralTO);
				requerimientos.add(reqTO);
			}
			
		}catch (Exception e) {
			logger.error(e, e);
		}finally{
			super.closeAll(con, ps, rs);
		}
		
		return requerimientos;
	}
	
	
	
	/**
	 * @param key
	 * @param idJefe
	 * @return
	 * @throws SQLException
	 */
	public Boolean updateJefeGral(Requerimiento req) throws SQLException{
		boolean resultado	= false;
		Connection con		= null;
		PreparedStatement ps= null;
		StringBuilder sql	= null;
		
		try{
			sql = new StringBuilder();
			sql.append("UPDATE sodexo.requerimiento SET jefaturaGral = ?, estado = ? WHERE idRequerimiento = ? ");
			
			con = super.loadConnection();
			ps	= con.prepareStatement(sql.toString());
			ps.setString(1, req.getJefaturaGral().getIdUsuario());
			ps.setString(2, req.getEstado().getIdEstado());
			ps.setString(3, req.getIdRequerimiento());
			ps.execute();
			
			resultado = true;
			
		}catch (Exception e) {
			logger.error(e, e);
		}finally{
			super.closeAll(con, ps, null);
		}
		
		return resultado;
	}
	
	/**
	 * @param reqTO
	 * @return
	 * @throws SQLException
	 */
	public Boolean updateRequerimientoOperativo(Requerimiento reqTO) throws SQLException{
		boolean resultado	= false;
		Connection con		= null;
		PreparedStatement ps= null;
		StringBuilder sql	= null;
		
		try{
			sql = new StringBuilder();
			sql.append("UPDATE sodexo.requerimiento ");
			sql.append("SET tiempoEstimado = ?, fechaEntrega = ?, jefeProyecto = ?, estado = ?, respuesta = ? ");
			sql.append("WHERE idRequerimiento = ? ");
			
			con = super.loadConnection();
			ps	= con.prepareStatement(sql.toString());
			ps.setString(1, reqTO.getTiempoEstimado());
			ps.setDate(2, new Date(FechaUtils.strToDate(reqTO.getFechaEntrega()).getTime()));
			ps.setString(3, reqTO.getJefeProyecto().getIdUsuario());
			ps.setString(4, reqTO.getEstado().getIdEstado());
			ps.setString(5, reqTO.getRespuesta());
			ps.setString(6, reqTO.getIdRequerimiento());
			ps.execute();
			
			resultado = true;
			
		}catch (Exception e) {
			logger.error(e, e);
		}finally{
			super.closeAll(con, ps, null);
		}
		
		return resultado;
	}

}
